//全局定义颜色
var Colors = {
   red:0xf25346,    
   white:0xd8d0d1,  
   brown:0x59332e,  
   pink:0xF5986E,   
   brownDark:0x23190f,  
   blue:0x68c3c0
};

var scene,
    camera, fieldOfView, aspectRatio, nearPlane, farPlane,
    renderer, container;


var HEIGHT, WIDTH,
    mousePos = { x: 0, y: 0 };

//页面加载完成，初始化
window.addEventListener('load', init, false);    

//初始化函数    
function init(event){
  document.addEventListener('mousemove', handleMouseMove, false);
  createScene();
  createLights();
  createPlane();
  //createSea();
  //createSky();
  loop();
}

function loop(){
  updatePlane();
  //sea.mesh.rotation.z += .005;
  //sky.mesh.rotation.z += .01;
  renderer.render(scene, camera);
  requestAnimationFrame(loop);
}

function updatePlane(){
  var targetY = normalize(mousePos.y,-.75,.75,25, 175);
  var targetX = normalize(mousePos.x,-.75,.75,-100, 100);
  //更新飞机位置
  airplane.mesh.position.y = targetY;
  airplane.mesh.position.x = targetX;
  //螺旋桨旋转（转轴与桨叶）
  airplane.propeller.rotation.x += 0.3;
}

function normalize(v,vmin,vmax,tmin, tmax){
  var nv = Math.max(Math.min(v,vmax), vmin);
  var dv = vmax-vmin;
  var pc = (nv-vmin)/dv;
  var dt = tmax-tmin;
  var tv = tmin + (pc*dt);
  return tv;
}

/*
function test() {
  // 创建场景
  var scene = new THREE.Scene();
  // 创建相机
  var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
  // 创建渲染器
  var renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );
  
  // 创建一个立方体（长宽高都是1 = 正方体）
  var geometry = new THREE.BoxGeometry( 1, 1, 1 );
  // MeshBasicMaterial 定义材质（颜色，线框，线框宽度等等）
  var material = new THREE.MeshBasicMaterial( { color: 0x46b0ff } );
  // 创建网格（网格需要一个几何体，以及一个或多个材质）
  var cube = new THREE.Mesh( geometry, material);
  // 网格添加到场景中
  scene.add(cube);
  // 相机的位置
  camera.position.z = 5; 
  // 每帧网格位置改变，这样才能看到动画效果
  var animate = function () {
    requestAnimationFrame( animate );
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera );
  }; 
  animate();
}
*/

//鼠标滚动事件
function handleMouseMove(event) {
  var tx = -1 + (event.clientX / WIDTH)*2;
  var ty = 1 - (event.clientY / HEIGHT)*2;
  mousePos = {x:tx, y:ty};
}

//窗口监听事件
function handleWindowResize() {
  HEIGHT = window.innerHeight;
  WIDTH = window.innerWidth;
  renderer.setSize(WIDTH, HEIGHT);
  camera.aspect = WIDTH / HEIGHT;
  camera.updateProjectionMatrix();
}

//创建场景，相机，渲染器
function createScene() {
  //获取窗口大小
  HEIGHT = window.innerHeight;
  WIDTH = window.innerWidth;
  //创建场景
  scene = new THREE.Scene();
  //宽高比
  aspectRatio = WIDTH / HEIGHT;
  fieldOfView = 60;
  nearPlane = 1;
  farPlane = 10000;
  //创建相机
  /*
   * PerspectiveCamera(fov, aspect, near, far)
   * Fov – 相机的视锥体的垂直视野角
   * Aspect – 相机视锥体的长宽比
   * Near – 相机视锥体的近平面
   * Far – 相机视锥体的远平面
   */
  camera = new THREE.PerspectiveCamera(
    fieldOfView,
    aspectRatio,
    nearPlane,
    farPlane
  );
  /*
    add(object)  用于向场景中添加对象。使用该方法还可以创建对象组。
    children  用于返回一个场景中所有对象的列表，包括摄像机和光源。  
    getObjectByName(name,recursive)  在创建对象时可以指定唯一的标识 name，使用该方法可以查找特定名字的对象。
      当参数 recursive 设置为 false 时，在调用者子元素上查找
      当参数 recursive 设置为 true 时，在调用者的所有后代对象上查找
    remove(object)  object 为场景中对象的引用，使用该方法可以将对象从场景中移除。  
    traverse(function)  该方法也可以遍历调用者和调用者的所有后代，
      function 参数是一个函数，被调用者和每一个后代对象调用 function 方法。  
    fog  使用该属性可以为场景添加雾化效果，可以产生隐藏远处物体的浓雾效果。  
    overrideMaterial  使用该属性可以强制场景中的所有物体使用相同的材质。
   */
  scene.fog = new THREE.Fog(0xf7d9aa, 100,950);
  //相机位置
  camera.position.x = 0;
  camera.position.z = 200;
  camera.position.y = 100;
  //渲染器
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(WIDTH, HEIGHT);
  //开启阴影（背影）效果
  renderer.shadowMap.enabled = true;
  //容器
  container = document.getElementById('world');
  container.appendChild(renderer.domElement);

  window.addEventListener('resize', handleWindowResize, false);
}

//创建灯光
var ambientLight, hemisphereLight, shadowLight;
function createLights() {
  //环境光
  hemisphereLight = new THREE.HemisphereLight(0xaaaaaa,0x000000, .9)
  //平行光
  shadowLight = new THREE.DirectionalLight(0xffffff, .9);
  shadowLight.position.set(150, 350, 350);
  shadowLight.castShadow = true;
  shadowLight.shadow.camera.left = -400;
  shadowLight.shadow.camera.right = 400;
  shadowLight.shadow.camera.top = 400;
  shadowLight.shadow.camera.bottom = -400;
  shadowLight.shadow.camera.near = 1;
  shadowLight.shadow.camera.far = 1000;
  shadowLight.shadow.mapSize.width = 2048;
  shadowLight.shadow.mapSize.height = 2048;
  scene.add(hemisphereLight);
  scene.add(shadowLight);
}

//物品3D模型
var sea;
var airplane;

//飞机模型
var AirPlane = function(){
  
  //创建物体基类对象（飞机对象）
	this.mesh = new THREE.Object3D();
  this.mesh.name = "airPlane";

  //创建一个盒子模型为驾驶舱
	var geomCockpit = new THREE.BoxGeometry(60,50,50,1,1,1);
  //驾驶舱材质
  //MeshPhongMaterial材质用于光亮表面的材质
  //着色类型：THREE.FlatShading平面着色
  var matCockpit = new THREE.MeshPhongMaterial({color:Colors.red, shading:THREE.FlatShading});
  //驾驶舱对象
  //Mesh网孔对象的基类，Mesh( geometry, material ) geometry是它的形状，material是它的材质
  var cockpit = new THREE.Mesh(geomCockpit, matCockpit);
	cockpit.castShadow = true; //把模型设置为生成投影
  cockpit.receiveShadow = true; //模型设置为接受阴影
  //添加驾驶舱对象为该对象的子对象。可以添加任意数量的对象。
  this.mesh.add(cockpit);

  //创建一个盒子模型为引擎
  var geomEngine = new THREE.BoxGeometry(20,50,50,1,1,1);
  //引擎材质
  var matEngine = new THREE.MeshPhongMaterial({color:Colors.white, shading:THREE.FlatShading});
  //引擎对象
  var engine = new THREE.Mesh(geomEngine, matEngine);
  engine.position.x = 40;
  engine.castShadow = true;
  engine.receiveShadow = true;
  //添加引擎对象到飞机里去
	this.mesh.add(engine);

  //创建一个盒子模型为水平尾翼
  var geomTailPlane = new THREE.BoxGeometry(15,20,5,1,1,1);
  var matTailPlane = new THREE.MeshPhongMaterial({color:Colors.red, shading:THREE.FlatShading});
  var tailPlane = new THREE.Mesh(geomTailPlane, matTailPlane);
  tailPlane.position.set(-35,25,0);
  tailPlane.castShadow = true;
  tailPlane.receiveShadow = true;
	this.mesh.add(tailPlane);

  //创建一个盒子模型为机翼
  var geomSideWing = new THREE.BoxGeometry(40,8,150,1,1,1);
  var matSideWing = new THREE.MeshPhongMaterial({color:Colors.red, shading:THREE.FlatShading});
  var sideWing = new THREE.Mesh(geomSideWing, matSideWing);
  sideWing.position.set(0,0,0);
  sideWing.castShadow = true;
  sideWing.receiveShadow = true;
	this.mesh.add(sideWing);

  //创建一个盒子模型为螺旋桨(实际这里是中间那根转轴)
  var geomPropeller = new THREE.BoxGeometry(20,10,10,1,1,1);
  var matPropeller = new THREE.MeshPhongMaterial({color:Colors.brown, shading:THREE.FlatShading});
  this.propeller = new THREE.Mesh(geomPropeller, matPropeller);
  this.propeller.castShadow = true;
  this.propeller.receiveShadow = true;

  //创建一个盒子模型为桨叶
  var geomBlade = new THREE.BoxGeometry(1,100,20,1,1,1);
  var matBlade = new THREE.MeshPhongMaterial({color:Colors.brownDark, shading:THREE.FlatShading});
  var blade = new THREE.Mesh(geomBlade, matBlade);
  blade.position.set(8,0,0);
  blade.castShadow = true;
  blade.receiveShadow = true;
  //添加桨叶对象到转轴上（因为旋转转轴也要动，到时候整个对象转动更好）
	this.propeller.add(blade);
  this.propeller.position.set(50,0,0);
  //添加整个螺旋桨到飞机对象里
  this.mesh.add(this.propeller);
};

//创建飞机
function createPlane(){
  //获取飞机对象
  airplane = new AirPlane();
  airplane.mesh.scale.set(.25,.25,.25);
  airplane.mesh.position.y = 100;
  //添加飞机到场景中
  scene.add(airplane.mesh);
}





